"use strict";

/**文件、目录删除函数
 * @param Paths 指定需要删除的目录或文件
 *
 * @description 本函数有两种执行删除的方式
 *
 * @description 1、使用node JS 内置的fs模块实现删除
 *
 * @description 2、使用node JS 内置的child_process模块调用已知的操作系统命令实现删除
 *
 * @example 使用fs模块的方式，
 * rmData("指定需要删除的文件或目录");
 *
 * @example 使用child_process模块调用操作系统命令的方式，
 * rmData("指定需要删除的文件或目录", "system");
 *
 * @description 注意，rmData函数的第二参数必须为system的字样，不区分大小写，才可实现调用操作系统命令实现删除文件或目录。
 * 调用操作系统命令仅支持linux、Windows系统，其他的系统暂未支持。
 *
 * @description 其他的字样或不传入该参数，默认使用fs模块的方式实现。
 * */
function rmData(Paths) {
    let Handle = {fs: require('fs'), ps: require('path'), child_system: require("child_process")};
    let dirContent = (Paths) => {
        let FinalArr = [];
        let recursion = (Path) => {
            let chk = Handle.fs.statSync(Path);
            if (chk.isFile()) {
                FinalArr.push(Path);
            } else if (chk.isDirectory()) {
                let list = Handle.fs.readdirSync(Path);
                FinalArr.push(Path);
                if (list.length > 0) {
                    for (let item in list) {
                        let url = Handle.ps.join(Path, list[item]);
                        let gds = Handle.fs.statSync(url);
                        if (gds.isFile()) {
                            FinalArr.push(url);
                        } else if (gds.isDirectory()) {
                            recursion(url);
                        }
                    }
                }
            }
        }
        recursion(Paths);
        return FinalArr;
    }
    let OperateWay;
    let FinalValue;
    try {
        if (typeof arguments[1] === "string") {
            switch (String(arguments[1]).toLowerCase()) {
                case "system":
                    OperateWay = "system";
                    break;
                default:
                    OperateWay = "default";
                    break;
            }
        } else {
            OperateWay = "default";
        }
        if (OperateWay === "system") {
            if (Handle.fs.existsSync(Paths)) {
                let det = Handle.fs.statSync(Paths);
                if (det.isFile()) {
                    switch (process.platform) {
                        case "linux":
                            FinalValue = Handle.child_system.execSync(`rm -f ${Paths}`).toString("utf8");
                            break;
                        case "win32":
                            FinalValue = Handle.child_system.execSync(`del /Q /F ${Paths}`).toString("utf8");
                            break;
                        default:
                            throw new Error("暂未支持当前的操作系统执行删除操作");
                    }
                } else if (det.isDirectory()) {
                    switch (process.platform) {
                        case "linux":
                            FinalValue = Handle.child_system.execSync(`rm -rf ${Paths}`).toString("utf8");
                            break;
                        case "win32":
                            FinalValue = Handle.child_system.execSync(`rmdir /Q /S ${Paths}`).toString("utf8");
                            break;
                        default:
                            throw new Error("暂未支持当前的操作系统执行删除操作");
                    }
                } else {
                    throw new Error("需要删除的目标不是目录也不是文件");
                }
            } else {
                throw new Error("需要删除的目标不存在");
            }
        } else {
            if (Handle.fs.existsSync(Paths)) {
                let det = Handle.fs.statSync(Paths);
                if (det.isFile()) {
                    Handle.fs.rmSync(Paths);
                } else if (det.isDirectory()) {
                    let list = dirContent(Paths);
                    if (list.length > 0) {
                        for (let item in list) {
                            let chk = Handle.fs.statSync(list[item]);
                            if (chk.isFile()) {
                                Handle.fs.rmSync(list[item]);
                            }
                        }
                        while (true) {
                            let pos = undefined;
                            let count = 0;
                            try {
                                for (let num = 0; num < list.length; num++) {
                                    if (!Handle.fs.existsSync(list[num])) {
                                        pos = num;
                                        count++;
                                        throw new Error("");
                                    }
                                }
                                if (count === 0) {
                                    break;
                                }
                            } catch (e) {
                                if (count > 0) {
                                    list.splice(pos, 1);
                                } else {
                                    break;
                                }
                            }
                        }
                        while (true) {
                            let pos = undefined;
                            let count = 0;
                            for (let item in list) {
                                let chk = Handle.fs.statSync(list[item]);
                                if (chk.isDirectory()) {
                                    try {
                                        Handle.fs.rmdirSync(list[item]);
                                        count++;
                                        pos = parseInt(item);
                                        list.splice(pos, 1);
                                    } catch (e) {

                                    }
                                }
                            }
                            if (list.length === 0) {
                                break;
                            }
                        }
                    } else {
                        Handle.fs.rmdirSync(Paths);
                    }
                } else {
                    throw new Error("需要删除的目标不是目录也不是文件");
                }
            } else {
                throw new Error("需要删除的目标不存在");
            }
        }
        if (FinalValue === undefined) {
            FinalValue = "";
        }
        return FinalValue;
    } catch (e) {
        return e.message;
    }
}

/**创建目录函数
 * @param Path 指定创建目录所在路径
 * @param DirectoryName 指定需要创建的目录名称
 *
 * @description 本函数有两种执行创建的方式
 *
 * @description 1、使用node JS 内置的fs模块实现创建
 *
 * @description 2、使用node JS 内置的child_process模块调用已知的操作系统命令实现创建
 *
 * @example 使用fs模块的方式，
 * createDirectory("指定需要创建的目录");
 * createDirectory("指定需要创建的目录的路径","目录名称");
 *
 * @example 使用child_process模块调用操作系统命令的方式，
 * createDirectory("指定需要创建的目录", "", "system");
 * createDirectory("指定需要创建的目录的路径","目录名称", "system");
 * */
function createDirectory(Path, DirectoryName) {
    let dirOperateHandle = {
        fs: require('fs'),
        ps: require('path'),
        child_system: require('child_process'),
        OriginInstance: undefined,
    };
    dirOperateHandle.OriginInstance = this;
    let OperateWay = "";
    let PathSplitSymbol = "";
    let SourcePath, TargetName, FinalOperateMessage = "";
    let FinalOperateTarget = "";
    try {
        let OperateApplet = () => {
            if (OperateWay === 'system') {
                switch (process.platform) {
                    case "linux":
                        FinalOperateMessage = dirOperateHandle.child_system.execSync(`mkdir ${FinalOperateTarget}`).toString("utf-8");
                        break;
                    case "win32":
                        FinalOperateMessage = dirOperateHandle.child_system.execSync(`mkdir ${FinalOperateTarget}`).toString("utf-8");
                        break;
                }
            } else {
                dirOperateHandle.fs.mkdirSync(FinalOperateTarget);
            }
        }
        switch (process.platform) {
            case "linux":
                PathSplitSymbol = "/";
                break;
            case "win32":
                PathSplitSymbol = "\\";
                break;
            default:
                throw new Error("无法识别当前的操作系统");
        }
        if (arguments.length === 1) {
            if (
                dirOperateHandle.OriginInstance.findMultiEqualString(String(Path).toString(), PathSplitSymbol, true, 0, 0) > 0
            ) {
                if (dirOperateHandle.fs.existsSync(dirOperateHandle.OriginInstance.getFileOnDirectoryLocation(Path))) {
                    SourcePath = dirOperateHandle.OriginInstance.getFileOnDirectoryLocation(Path);
                    TargetName = dirOperateHandle.OriginInstance.getFullPathFileOrDirectoryName(Path);
                    FinalOperateTarget = Path;
                } else {
                    throw new Error("目标位置无效");
                }
            } else {
                throw new Error("目标位置不符合当前的操作系统");
            }
            OperateWay = "default";
        } else if (arguments.length >= 2) {
            if (dirOperateHandle.OriginInstance.findMultiEqualString(String(Path).toString(), PathSplitSymbol, true, 0, 0) > 0) {
                if (dirOperateHandle.fs.existsSync(Path)) {
                    SourcePath = Path;
                } else {
                    let test = String(Path).split(PathSplitSymbol);
                    test.forEach((value, index, array) => {
                        if (value === '') {
                            array.splice(index, 1);
                        }
                    })
                    if (test.length > 1) {
                        TargetName = test.pop();
                        SourcePath = test.join(PathSplitSymbol)
                    } else {
                        throw new Error("指定路径不合法");
                    }
                }
            } else {
                throw new Error("目标位置不符合当前的操作系统");
            }
            if (typeof DirectoryName === 'string') {
                if (String(DirectoryName).length > 0) {
                    TargetName = DirectoryName;
                } else if (String(TargetName).length === 0) {
                    TargetName = dirOperateHandle.OriginInstance.getFullPathFileOrDirectoryName(SourcePath);
                }
            } else {
                throw new Error("");
            }
            if (typeof arguments[2] === 'string' && String(arguments[2]).toLowerCase() === "system") {
                OperateWay = "system";
            } else {
                OperateWay = "default";
            }
            FinalOperateTarget = dirOperateHandle.ps.join(SourcePath, TargetName);
        } else {
            throw new Error("");
        }
        OperateApplet();
        return FinalOperateMessage;
    } catch (e) {
        let ErrorMessageArray;
        if (String(e.message).indexOf(":") >= 0) {
            ErrorMessageArray = String(e.message).split(':');
            switch (ErrorMessageArray[0].toLowerCase()) {
                case "eexist":
                    throw new Error(`已存在名称相同的目录！`);
                case "eacces":
                    throw new Error(`当前指定的目录位置的权限拒绝创建目录！`);
                default:
                    throw new Error(`出现未知的错误！目录 ${TargetName} 无法创建！`);
            }
        } else {
            throw new Error(e.message);
        }
    }
}

/**特殊保留字符检测*/
function SpecialReservedCharacterDetect(StringData, NeedDetectChar) {

    let DisableSymbol;//字符库存储变量
    let FinalDetectValue = false;//最终检测值，True Or False

    //根据运行环境类别载入字符库
    switch (process.platform) {
        case "linux":
            DisableSymbol = [':', '/', '\\', '?', '*', '\"', '<', '>', '|', '\''];
            break;
        case "win32":
            DisableSymbol = [':', '/', '\\', '?', '*', '\"', '<', '>', '|'];
            break;
    }

    if (Object.prototype.toString.call(NeedDetectChar) === "[object String]") {
        if (StringData.indexOf(NeedDetectChar) >= 0) {
            FinalDetectValue = true;
        }
    } else {
        for (let SRcd in DisableSymbol) {
            if (StringData.indexOf(DisableSymbol[SRcd]) >= 0) {
                FinalDetectValue = true;
                break;
            }
        }
    }
    return FinalDetectValue;
}

/**获取全路径的文件、目录名称*/
function getFullPathFileOrDirectoryName(FullPathData) {
    let detectString;
    let FinalGetData;

    let sybchk = (StringData, NeedDetectChar) => {
        let srSymbols;
        let FinalDetectValue = false;
        switch (process.platform) {
            case "linux":
                srSymbols = [':', '/', '\\', '?', '*', '\"', '<', '>', '|', '\''];
                break;
            case "win32":
                srSymbols = [':', '/', '\\', '?', '*', '\"', '<', '>', '|'];
                break;
        }
        if (Object.prototype.toString.call(NeedDetectChar) === "[object String]") {
            if (StringData.indexOf(NeedDetectChar) >= 0) {
                FinalDetectValue = true;
            }
        } else {
            for (let SRcd in srSymbols) {
                if (StringData.indexOf(srSymbols[SRcd]) >= 0) {
                    FinalDetectValue = true;
                    break;
                }
            }
        }
        return FinalDetectValue;
    }

    if (Object.prototype.toString.call(FullPathData) === "[object String]") {
        switch (process.platform) {
            case "linux":
                detectString = "/";
                break;
            case "win32":
                detectString = "\\";
                break;
        }
        if (sybchk(FullPathData, detectString)) {
            for (let pointCount = FullPathData.length; pointCount >= 0; pointCount--) {
                if (FullPathData.charAt(pointCount) === detectString) {
                    FinalGetData = FullPathData.substr(pointCount + 1);
                    break;
                }
            }
        } else {
            throw new Error("貌似路径格式不合法！");
        }
    } else {
        throw new Error("全路径数据必须是字符串！");
    }
    return FinalGetData;
}

/**获取文件名的拓展名（后缀名）*/
function getFileNameExtName(FullFileName) {
    let finalExtName;
    if (Object.prototype.toString.call(FullFileName) === "[object String]" && FullFileName.length > 0) {
        if (FullFileName.indexOf(".") >= 0 && FullFileName.length > 1) {
            let dio;
            for (let deCount = (FullFileName.length); ; deCount--) {
                if (FullFileName.charAt(deCount) === ".") {
                    dio = deCount;
                    break;
                }
            }
            finalExtName = FullFileName.substr(dio);
        } else {
            finalExtName = '';
        }
    } else {
        finalExtName = '';
    }
    return finalExtName;
}

/**获取文件所在目录位置*/
function getFileOnDirectoryLocation(FullFilePath) {
    let finalFileOnPath;
    if (Object.prototype.toString.call(FullFilePath) === "[object String]") {
        if (FullFilePath.indexOf("\\") >= 0 || FullFilePath.indexOf("/") >= 0) {
            let currentRightOneSTSymbolLocation;
            currentRightOneSTSymbolLocation = FullFilePath.length;
            for (; currentRightOneSTSymbolLocation >= 0; currentRightOneSTSymbolLocation--) {
                if (FullFilePath.charAt(currentRightOneSTSymbolLocation) === "\\" || FullFilePath.charAt(currentRightOneSTSymbolLocation) === "/") {
                    break;
                }
            }
            if (currentRightOneSTSymbolLocation === 0) {
                finalFileOnPath = FullFilePath.substr(0, 1);
            } else {
                finalFileOnPath = FullFilePath.substr(0, currentRightOneSTSymbolLocation);
            }
        } else {
            finalFileOnPath = undefined;
        }
    } else {
        finalFileOnPath = undefined;
    }
    return finalFileOnPath;
}

/**获取当前运行的JavaScript脚本所在的目录路径*/
function getCurrentShellScriptPath() {
    let path = require('path');
    let currentShellJavaScript = process.argv[1];
    return path.dirname(currentShellJavaScript);
}

let {zip_DeCompress, zip_EnCompress} = require("./zipArchiveFileProcess");

module.exports = {
    rmData,
    createDirectory,
    SpecialReservedCharacterDetect,
    getFullPathFileOrDirectoryName,
    getFileNameExtName,
    getFileOnDirectoryLocation,
    getCurrentShellScriptPath,
    zip_DeCompress,
    zip_EnCompress
};